package com.mdd.common.service.impl;

import com.alibaba.fastjson2.JSONArray;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Assert;
import com.mdd.common.core.AjaxResult;
import com.mdd.common.entity.*;
import com.mdd.common.entity.article.ArticleCategory;
import com.mdd.common.entity.user.User;
import com.mdd.common.enums.*;
import com.mdd.common.exception.OperateException;
import com.mdd.common.mapper.*;
import com.mdd.common.mapper.article.ArticleCategoryMapper;
import com.mdd.common.mapper.user.UserMapper;
import com.mdd.common.service.ILabelIndexService;
import com.mdd.common.service.IPushService;
import com.mdd.common.service.IRegionService;
import com.mdd.common.util.*;
import com.mdd.common.validate.LabelIndexSearchValidate;
import com.mdd.common.validate.push.PushInfoApplyValidate;
import com.mdd.common.vo.LabelDataVo;
import com.mdd.common.vo.LabelVo;
import com.mdd.common.vo.business.BusinessSubmitResultVo;
import com.mdd.common.vo.business.VersionVo;
import com.mdd.common.vo.push.PushInfoDetialVo;
import com.mdd.common.vo.push.PushInfoIndexVo;
import com.mdd.common.vo.topset.TopSetVo;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;


import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class PushServiceimpl implements IPushService {

    @Resource
    ArticleCategoryMapper articleCategoryMapper;

    @Resource
    LabelMapper labelMapper;

    @Resource
    UserMapper userMapper;

    @Resource
    PushInfoMapper pushInfoMapper;

    @Resource
    TopSetMapper topSetMapper;

    @Resource
    PushFileMapper pushFileMapper;

    @Resource
    LabelIndexMapper labelIndexMapper;

    @Resource
    IRegionService regionService;

    @Resource
    ILabelIndexService labelIndexService;


    @Override
    public void pushClass2Redis() {
        List<ArticleCategory> list = getArticleCategoryList();
        if (Objects.nonNull(list) && list.size() > 0) {
            RedisUtils.set(RedisKey.PUSH_CLASS.getKey(), list);
        }
    }

    @Override
    public TopSetVo config() {
        TopSetVo vo = new TopSetVo();
        Map<String, String> topSet = ConfigUtils.get("topSet");
        String num = topSet.getOrDefault("num", "0");
        String iconUrl = topSet.getOrDefault("iconUrl", "");
        String titleName = topSet.getOrDefault("titleName", "");
        String titleDesc = topSet.getOrDefault("titleDesc", "");
        String titleTag = topSet.getOrDefault("titleTag", "");
        String visitMin = topSet.getOrDefault("visitMin", "");
        String visitMax = topSet.getOrDefault("visitMax", "");
        String openReview = topSet.getOrDefault("openReview", "");

        vo.setNum(StringUtils.isNotBlank(num) ? Integer.parseInt(num) : 0);
        vo.setIconUrl(UrlUtils.toAbsoluteUrl(iconUrl));
        vo.setTitleName(titleName);
        vo.setTitleDesc(titleDesc);
        vo.setTitleTag(titleTag);
        vo.setVisitMin(visitMin);
        vo.setVisitMax(visitMax);
        vo.setOpenReview(Integer.valueOf(openReview));
        return vo;
    }

    @Override
    public List<ArticleCategory> getArticleCategoryList() {
        LambdaQueryWrapper<ArticleCategory> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(ArticleCategory::getIsDelete, 0).eq(ArticleCategory::getIsShow, 1).eq(ArticleCategory::getType, 1).orderByDesc(ArticleCategory::getType);
        List<ArticleCategory> list = articleCategoryMapper.selectList(wrapper);
        list.forEach(item -> {
            item.setIconUrl(UrlUtils.toAbsoluteUrl(item.getIconUrl()));
        });
        return list;
    }

    @Override
    public List<ArticleCategory> getPushClass() {
        List<ArticleCategory> result;
        Object data = RedisUtils.get(RedisKey.PUSH_CLASS.getKey());
        if (Objects.nonNull(data)) {
            result = (List<ArticleCategory>) data;
        } else {
            result = getArticleCategoryList();
        }
        return result;
    }

    @Override
    public List<LabelDataVo> getLabelList(Integer categoryId) {
        LabelIndexSearchValidate req = new LabelIndexSearchValidate();
        req.setSourceId(categoryId + "");
        req.setSourceType(SourceTypeEnum.ARTICLE_CATEGORY_ID.getKey());

        List<LabelDataVo> labelList = labelMapper.getLabelList(req);
        return labelList;
    }

    /**
     * 发布初始化
     *
     * @param categoryId
     * @param userId
     * @return
     */
    @Override
    public PushInfoIndexVo getPushIndex(Integer categoryId, Integer userId) {
        ArticleCategory category = articleCategoryMapper.selectById(categoryId);
        Assert.notNull(category, "分类不存在");

        PushInfoIndexVo data = new PushInfoIndexVo();
        data.setCategoryId(categoryId);
        data.setCategoryName(category.getName());

        // 获取分类标签
        data.setLabelList(getLabelList(categoryId));

        // 用户信息
        User user = userMapper.selectById(userId);
        if (Objects.nonNull(user)) {
            data.setContact(user.getRealName());
            data.setMobile(user.getMobile());
        }
        // 发布条数
        Map<String, String> topSet = ConfigUtils.get("topSet");
        String num = topSet.getOrDefault("num", "0");

        LambdaQueryWrapper<PushInfo> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(PushInfo::getUserId, userId);
        wrapper.eq(PushInfo::getIsDelete, 0);
        Integer pushNum = pushInfoMapper.selectCount(wrapper).intValue();

        if (pushNum >= Integer.parseInt(num)) {
            data.setPushNum(0);
        } else {
            data.setPushNum(Integer.parseInt(num) - pushNum);
        }
        List<TopSet> setList = topSetMapper.selectList(new QueryWrapper<TopSet>().eq("is_show", 1).eq("is_delete", 0).orderByDesc(Arrays.asList("sort")));

        List<VersionVo> banbenList = new ArrayList<>();
        setList.forEach(item -> {
            VersionVo vo = new VersionVo();
            vo.setId(item.getId());
            vo.setName("置顶" + item.getDays() + "天");
            vo.setDescription(item.getRemark());
            vo.setSellPrice(String.valueOf(item.getPrice()));
            banbenList.add(vo);
        });
        data.setBanbenList(banbenList);
        return data;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public BusinessSubmitResultVo submitPushInfo(PushInfoApplyValidate applyValidate) {
        // 发布表插入数据
        PushInfo info = addPushInfo(applyValidate);
        applyValidate.setSourceId(info.getId() + "");
        applyValidate.setSourceType(SourceTypeEnum.BUSINESS_ID.getKey());

        BusinessSubmitResultVo vo = new BusinessSubmitResultVo();

        Integer goodId = applyValidate.getGoodId();
        if (Objects.nonNull(goodId) && goodId > 0) {
            String orderSn = pushInfoMapper.randMakeOrderSn("order_sn");
            TopSet topSet = topSetMapper.selectById(goodId);
            vo.setOrderId(info.getId());
            vo.setNeedPayMoney(topSet.getPrice());
            vo.setOrderSn(orderSn);
            vo.setNeedPay(true);

            info.setOrderSn(orderSn);
            info.setPrice(topSet.getPrice());
            info.setStatus(PushInfoEnum.STATUS_WAIT_PAY.getCode());
        } else {
            // 发布条数
            Map<String, String> config = ConfigUtils.get("topSet");
            String num = config.getOrDefault("num", "0");

            LambdaQueryWrapper<PushInfo> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(PushInfo::getUserId, applyValidate.getUserId());
            wrapper.eq(PushInfo::getIsDelete, 0);
            Integer pushNum = pushInfoMapper.selectCount(wrapper).intValue();

            if (pushNum >= Integer.parseInt(num)) {
                throw new OperateException("免费发布次数用尽，请选择置顶！");
            }

            vo.setNeedPayMoney(BigDecimal.ZERO);

            String openReview = config.getOrDefault("openReview", "");
            if ((BusinessEnum.BUSINESS_STATUS_COMPLETED.getCode() + "").equals(openReview)) {
                info.setStatus(BusinessEnum.BUSINESS_STATUS_COMPLETED.getCode());
                info.setTitleName(info.getContent().length() > 16 ? info.getContent().substring(0, 15) : info.getContent());
            } else {
                info.setStatus(BusinessEnum.BUSINESS_STATUS_WAIT_REVIEW.getCode());
            }

        }
        pushInfoMapper.updateById(info);
        return vo;
    }

    /**
     * pages/push/push_list 初始化筛选条件
     *
     * @return
     */
    @Override
    public AjaxResult<Object> getPushInfoListConfig() {
        Map<String, Object> result = new HashMap<>();

        // 地区
        JSONArray areaList = regionService.getList();
        result.put("areaList", areaList);
        // 发布分类
        List<LabelVo> categoryList = new ArrayList<>();
        List<ArticleCategory> list = getPushClass();
        list.forEach(item -> {
            LabelVo vo = new LabelVo();
            vo.setValue(item.getId() + "");
            vo.setLabel(item.getName());
            vo.setLabelList(getLabelList(item.getId()));
            categoryList.add(vo);
        });
        result.put("categoryList", categoryList);
        return AjaxResult.success(result);
    }

    @Override
    public PushInfoDetialVo getPushInfoDetail(Integer id) {
        PushInfo model = pushInfoMapper.selectOne(new QueryWrapper<PushInfo>().select(PushInfo.class, info -> !info.getColumn().equals("is_delete") && !info.getColumn().equals("delete_time")).eq("id", id).eq("is_delete", 0));

        Assert.notNull(model, "发布不存在");

        Map<String, String> config = ConfigUtils.get("topSet");
        String visitMin = config.getOrDefault("visitMin", "");
        String visitMax = config.getOrDefault("visitMax", "");

        BigDecimal bd = new BigDecimal(Math.random() * (Integer.valueOf(visitMax) - Integer.valueOf(visitMin)) + Integer.valueOf(visitMin));

        model.setVisit(model.getVisit() + bd.intValue());
        pushInfoMapper.updateById(model);

        PushInfoDetialVo vo = new PushInfoDetialVo();
        BeanUtils.copyProperties(model, vo);
        vo.setContent(StringUtils.isNull(model.getContent()) ? "" : model.getContent());
        // 分类所有标签
        LabelIndexSearchValidate req = new LabelIndexSearchValidate();
        req.setSourceId(model.getCategoryId() + "");
        req.setSourceType(SourceTypeEnum.ARTICLE_CATEGORY_ID.getKey());
        List<LabelDataVo> labelDataVos = labelIndexService.getLabelList(req);
        List<String> labelList = labelDataVos.stream().map(LabelDataVo::getLabel).collect(Collectors.toList());
        if (Objects.nonNull(labelList) && labelList.size() > 0) {
            vo.setLabelList(labelList);
        }
        // 发布信息的标签
        LabelIndexSearchValidate req1 = new LabelIndexSearchValidate();
        req1.setSourceId(model.getId() + "");
        req1.setSourceType(SourceTypeEnum.PUSH_INFO_ID.getKey());
        List<LabelDataVo> pushInfoLabels = labelIndexService.getLabelList(req1);
        List<String> pushLabels = pushInfoLabels.stream().map(LabelDataVo::getLabel).collect(Collectors.toList());
        if (Objects.nonNull(pushLabels) && pushLabels.size() > 0) {
            vo.setPushLabels(pushLabels);
            vo.setPushLabelList(pushInfoLabels);
        }
        // 查询文件
        LambdaQueryWrapper<PushFile> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(PushFile::getPushInfoId, model.getId()).eq(PushFile::getIsDelete, 0);
        List<PushFile> pushFiles = pushFileMapper.selectList(queryWrapper);
        List<PushFile> videoUrlList = pushFiles.stream().filter(item -> item.getFileType().equals(AlbumEnum.Video.getCode())).collect(Collectors.toList());

        if (Objects.nonNull(videoUrlList) && videoUrlList.size() > 0) {
            List<String> videoUrls = new ArrayList<>();
            videoUrlList.forEach(item -> {
                videoUrls.add(UrlUtils.toAbsoluteUrl(item.getFileUrl()));
            });
            vo.setVideoUrls(videoUrls);
        }


        List<PushFile> imageUrlList = pushFiles.stream().filter(item -> item.getFileType().equals(AlbumEnum.IMAGE.getCode())).collect(Collectors.toList());

        if (Objects.nonNull(imageUrlList) && imageUrlList.size() > 0) {
            List<String> imageUrls = new ArrayList<>();
            imageUrlList.forEach(item -> {
                imageUrls.add(UrlUtils.toAbsoluteUrl(item.getFileUrl()));
            });
            vo.setImageUrls(imageUrls);
        }
        vo.setCreateTime(TimeUtils.timestampToDate(model.getCreateTime()));
        // 分类名称
        ArticleCategory category = articleCategoryMapper.selectById(model.getCategoryId());
        vo.setCategoryName(Objects.nonNull(category) ? category.getName() : "");

        // 置顶样式 分类样式
        LabelDataVo topStyle = labelIndexService.getLabelInfo(LabelTypeEnum.LABEL_TOP_UP.getKey());
        vo.setTopStyle(topStyle);
        LabelDataVo categoryStyle = labelIndexService.getLabelInfo(LabelTypeEnum.CATEGORY_LABEL.getKey());

        vo.setCategoryStyle(categoryStyle);
        return vo;
    }

    private PushInfo addPushInfo(PushInfoApplyValidate applyValidate) {
        PushInfo info = new PushInfo();
        // 省市区

        info.setProvinceId(applyValidate.getProvinceId());
        info.setCityId(applyValidate.getCityId());
        info.setDistrictId(applyValidate.getDistrictId());

        info.setLatitude(applyValidate.getLatitude());
        info.setLongitude(applyValidate.getLongitude());
        info.setAddress(applyValidate.getAddress());

        info.setContent(applyValidate.getContent());

        info.setContact(applyValidate.getContact());
        info.setMobile(applyValidate.getMobile());

        info.setUserId(applyValidate.getUserId());
        info.setCreateTime(TimeUtils.timestamp());
        info.setUpdateTime(TimeUtils.timestamp());
        info.setCategoryId(applyValidate.getCategoryId());
        pushInfoMapper.insert(info);

        Integer infoId = info.getId();

        // 视频
        List<String> videoUrls = applyValidate.getVideoUrls();
        if (Objects.nonNull(videoUrls) && videoUrls.size() > 0) {
            videoUrls.forEach(item -> {
                PushFile file = new PushFile();
                file.setPushInfoId(infoId);
                file.setFileType(AlbumEnum.Video.getCode());
                file.setFileUrl(UrlUtils.toRelativeUrl(item));
                file.setCreateTime(TimeUtils.timestamp());
                file.setUpdateTime(TimeUtils.timestamp());
                pushFileMapper.insert(file);
            });
        }
        // 照片
        List<String> imageUrls = applyValidate.getImageUrls();
        if (Objects.nonNull(imageUrls) && imageUrls.size() > 0) {
            imageUrls.forEach(item -> {
                PushFile file = new PushFile();
                file.setPushInfoId(infoId);
                file.setFileType(AlbumEnum.IMAGE.getCode());
                file.setFileUrl(UrlUtils.toRelativeUrl(item));
                file.setCreateTime(TimeUtils.timestamp());
                file.setUpdateTime(TimeUtils.timestamp());
                pushFileMapper.insert(file);
            });
        }
        // 标签处理
        List<Integer> labelList = applyValidate.getLabelList();

        labelList.forEach(item -> {
            LabelIndex labelIndex = new LabelIndex();
            labelIndex.setLabelId(item);
            labelIndex.setSourceId(infoId + "");
            labelIndex.setSourceType(SourceTypeEnum.PUSH_INFO_ID.getKey());
            labelIndex.setCreateTime(TimeUtils.timestamp());
            labelIndex.setUpdateTime(TimeUtils.timestamp());
            labelIndexMapper.insert(labelIndex);
        });
        return info;
    }
}
